/* 
 * File:   UndoableRedoableCommand.h
 * Author: Gab'z
 *
 * Created on 25 mai 2012, 17:26
 */

#ifndef UNDOABLEREDOABLECOMMAND_H
#define	UNDOABLEREDOABLECOMMAND_H

#include "../command/Command.h"
#include "../../exception/MementoException.h"

namespace calculator {
    class Memento;

    /**
     * Classe de base des commandes annulables/réexécutables.
     * Non instanciable.
     * Design Pattern Command.
     */
    class UndoableRedoableCommand : public Command {
    public:

        /**
         * Méthode virtuelle pure d'entrée du Design Pattern Command.
         * Utilisation avec le Design Pattern Template Method, la méthode 
         * appelée est précisée par les filles.
         */
        virtual void execute() const throw (CommandException) = 0;

        /**
         * Vérifie si la commande est exécutable.
         * Méthode virtuelle pure appelée avant execute() afin de 
         * vérifier les paramètres et l'état des piles. @see Parameters, StackList, Stack
         * @return une std::string vide si la commande est exécutable,
         * sinon renvoie soit la raison de l'erreur dans la plupart des cas,
         * ou dans le cas d'une Expression renvoie le restant non exécuté de l'expression.
         */
        virtual std::string isExecutable() const = 0;

        /**
         * Clone la commande.
         * On ne peut pas créer de commandes (sauf des constantes) directement,
         * c'est le rôle du CommandManager, on a cependant besoin de les copier
         * pour les sauvegardes et la fonction UNDO/REDO.
         * @return une copie de la commande.
         */
        virtual UndoableRedoableCommand* clone() const = 0;
        
        /**
         * Permet d'annuler les modificatinos effectuées par la commande
         * et déplace l'itérateur de MementoCaretaker vers le Memento suivant.
         * 
         */
        void undo() const throw (CommandException);

        /**
         * Rejoue la commande mémorisée et déplace l'itérateur.
         * de MementoCaretaker vers le Memento suivant.
         */
        void redo() const throw (CommandException);

        /**
         * Crée un Memento propre à chaque Command contenant une copie
         * des données qui vont être modifiées.
         * @return un Memento spécialisé.
         */
        virtual const Memento* createMemento() const throw (CommandException) = 0;
        
        /**
         * Restaure le Context dans l'état précédent l'exécution de la commande
         * @param memento le Memento contenant les données à restituer
         */
        virtual void restoreFromMemento(const Memento* memento) const throw (MementoException) = 0;
        
        /**
         * Destructeur de UndoableRedoableCommand.
         */
        virtual ~UndoableRedoableCommand();

    protected:
        /**
         * Constructeur de UndoableRedoableCommand.
         * Chaque commande est défini par son nom. @see Command
         * @param name le nom de la commande.
         */
        UndoableRedoableCommand(const std::string name);

    private:
    };
}
#endif	/* UNDOABLEREDOABLECOMMAND_H */

